#pragma once

#include "buffer.hpp"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <memory>
#include <atomic>

namespace Log
{
    using Functor = std::function<void(Buffer &)>;
    enum class AsyncType
    {
        ASYNC_SAFE,  // 安全状态，缓冲区满了阻塞，避免资源耗尽的风险
        ASYNC_UNSAFE // 不考虑资源耗尽的问题，缓冲区满了就扩容，用于测试
    };

    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor &cb, AsyncType looper_type = AsyncType::ASYNC_SAFE)
            : _looper_type(AsyncType::ASYNC_SAFE),
              _stop(false),
              _thread(std::thread(&AsyncLooper::threadEntry, this)),
              _callBack(cb)
        {
        }

        ~AsyncLooper()
        {
            stop();
        }

        void stop()
        {
            _stop = true;
            _cond_con.notify_all(); // 唤醒所有工作线程
            _thread.join();         // 等待工作线程退出
        }

        void write(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 条件变量控制，若缓冲区剩余空间大小大于等于数据长度，则可以添加数据
            if (_looper_type == AsyncType::ASYNC_SAFE)
                _cond_pro.wait(lock, [&]()
                               { return _pro_buf.writeAbleSize() >= len; });
            _pro_buf.write(data, len);
            _cond_con.notify_one(); // 唤醒消费者处理缓冲区中的数据
        }

    private:
        void threadEntry() // 线程入口函数
        {
            while (1)
            {
                // 为互斥锁添加一个生命周期，缓冲区交换完毕后释放
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    // 退出标志被设置且缓冲区无数据再退出，否则可能会造成缓冲区有数据没，没有被完全处理
                    if (_stop && _pro_buf.empty())
                        break;
                    // 判断生产缓冲区有无数据，有则交换，无则阻塞
                    // 若是退出前被唤醒，或有数据被唤醒，则向下处理数据，否则陷入休眠
                    _cond_con.wait(lock, [&]()
                                   { return _stop || !_pro_buf.empty(); });
                    _con_buf.swap(_pro_buf);
                    // 唤醒生产者
                    if (_looper_type == AsyncType::ASYNC_SAFE)
                        _cond_pro.notify_all();
                }
                // 对消费者缓冲区数据进行处理
                _callBack(_con_buf);
                // 初始化消费者缓冲区
                _con_buf.reset();
            }
        }

    private:
        Functor _callBack; // 具体对缓冲区数据进行处理的回调函数，由异步工作器使用者传入

    private:
        AsyncType _looper_type;
        std::atomic<bool> _stop; // 工作器停止标志
        Buffer _pro_buf;         // 生产者缓冲区
        Buffer _con_buf;         // 消费者缓冲区
        std::mutex _mutex;
        std::condition_variable _cond_pro;
        std::condition_variable _cond_con;
        std::thread _thread; // 异步工作器的工作线程
    };
}